package net.chromedpork.hypertext.filtration;



import java.util.HashMap;
import java.util.Map;

import org.htmlcleaner.TagNode;
import org.htmlcleaner.XPatherException;

import net.chromedpork.hypertext.validation.Assertion;



/**
 *
 *  Map Filter object.
 *
 *  @author Inode <inode@chromedpork.net>
 * 
 */


public class MapFilterObject implements Filter
{
    private final String   keyXPath;
    private final String   valueXPath;
    private final String   returnAttribute;
    


    /**
     *
     *  Constructs a map filter object with preconfigured key and value
     *  XPath expression fields.
     *
     *  @param keyXPath     XPath expression to escrow key data
     *  @param valueXPath   XPath expression to escrow value data
     *
     */

    MapFilterObject(String keyXPath,
                    String valueXPath)
    {
        Assertion.notNull(keyXPath, "key XPath is null");
        Assertion.notNull(valueXPath, "value XPath is null");

        this.keyXPath        = keyXPath;
        this.valueXPath      = valueXPath;
        this.returnAttribute = null;
    }



    /**
     *
     *  Constructs a map filter object with preconfigured key and value
     *  XPath expression fields, plus an indicator to return the value of a
     *  tag attribute once XPath expressions have been evaluated.
     *
     *  @param keyXPath         XPath expression to escrow key data
     *  @param valueXPath       XPath expression to escrow value data
     *  @param returnAttribute  name of tag attribute whose value is required
     *
     */
    
    MapFilterObject(String keyXPath,
                    String valueXPath,
                    String returnAttribute)
    {
        Assertion.notNull(keyXPath, "key XPath is null");
        Assertion.notNull(valueXPath, "value XPath is null");
        Assertion.notNull(returnAttribute, "return attribute is null");

        this.keyXPath        = keyXPath;
        this.valueXPath      = valueXPath;
        this.returnAttribute = returnAttribute;
    }



    /**
     *
     *  Parses a tree of TagNodes, and generates a KV map of resultant
     *  data from the evaluation of key and value XPath expressions against
     *  the tree.
     *
     *  @param root     root node of the desired tag hierarchy.
     *
     *  @return result Map
     *
     *  @throws FilterException
     *
     */

    public Map<String, String> parse(TagNode root) throws FilterException
    {
        Assertion.notNull(root, "tag root is null");


        Map<String, String> result = new HashMap<String, String>();
        
        Object[] keys   = null;
        Object[] values = null;

        
        try
        {
            keys = root.evaluateXPath(keyXPath);
            values = root.evaluateXPath(valueXPath);
        }

        catch (XPatherException exception)
        {
            throw new FilterException(exception.getMessage());
        }


        for (int index = 0; index < values.length; index++)
        {
            String key   = null;
            String value = null;


            if (keys[index] instanceof StringBuffer)
            {
                key = keys[index].toString();
            }

            else
            {
                TagNode keyTag = (TagNode)values[index];
                key = keyTag.getText().toString();
            }


            if (values[index] instanceof StringBuffer)
            {
                value = values[index].toString();
            }

            else
            {
                if (returnAttribute != null)
                {
                    TagNode valueTag = (TagNode)values[index];
                    value = valueTag.getAttributeByName(returnAttribute);
                }

                else
                {
                    TagNode valueTag = (TagNode)values[index];
                    value = valueTag.getText().toString();
                }
            }

            result.put(key, value);
        }


        return (result);
    }
}
